import React, { useState, useEffect, useRef } from 'react';
import ContentEditable from 'react-contenteditable';
import TheInputVariableDropdown from "../TheInputVariableDropdown";

const TextComponent = ({
  index, listIndex, element, variables, showVariableSelector,
  setShowVariableSelector, handleChange
}) => {
  let { name, value } = element;

  const cursorPositionRef = useRef(null)
  const [cursorPosition, setCursorPosition] = useState(0);

  initCursorPosition(cursorPositionRef.current);

  useEffect(() => {
    cursorPositionRef.current = cursorPosition
    checkSlashAndToggleVariableSelector();
  }, [cursorPosition])

  const handleContentChange = (e) => {
    handleChange(index, formatText(e.target.value));
  };

  const extractRawTextFromHtml = (html) => {
    const parser = new DOMParser();
    const doc = parser.parseFromString(html, 'text/html');

    const spans = doc.querySelectorAll('.user-input');
    spans.forEach(span => {
      const inputElement = span.querySelector('input[type="hidden"]');
      const uuid = inputElement ? inputElement.value : null;

      const variableName = span.querySelector('.nodeVariable')?.textContent;
      if (uuid && variableName) {
        const replaceText = `{{#${uuid}.${variableName}#}}`;
        const textNode = document.createTextNode(replaceText);
        span.parentNode.replaceChild(textNode, span);
      }
    });

    return doc.body.textContent;
  };

  const formatText = (text) => {
    const regex = /{{#([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})\.(\w+)#}}/g;

    return text.replace(regex, (match, uuid, varname) => {
      const variable = variables.find(v => v.id === uuid && v.variableName === varname);
      if (variable) {
        return `<div class="user-input" contenteditable="false">
                  <span class="inputVarSpan">
                    <span class="inputVarSymbol star-symbol">{*}</span>
                    <span class="nodeLabel">${variable.nodeLabel}</span>
                    <span class="divideSymbol">|</span>
                    <span class="inputVarSymbol x-symbol">{x}</span>
                    <span class="nodeVariable">${variable.variableName}</span>
                  </span>
                  <input type="hidden" id="variableId" value="${uuid}">
                </div>`;
      }
      return `${match}`;
    });
  };

  value = formatText(extractRawTextFromHtml(value));

  const handleSelectVariable = (variable) => {
    const variableString = `{{#${variable.id}.${variable.variableName}#}}`;

    const updatedText = value.substring(0, cursorPositionRef.current) + variableString + value.substring(cursorPositionRef.current + 1);
    value = updatedText;

    setShowVariableSelector(false);
    handleChange(index, formatText(updatedText));
  };

  const handleKeyUp = (e) => {
    setCursorPosition(getCursorPosition());
  };

  const handleKeyDown = (event) => {
    if (event.key === 'Enter' && !event.shiftKey) {
      event.preventDefault();
    }
  }

  const handleClick = (e) => {
    setCursorPosition(getCursorPosition());
  };

  function initCursorPosition(position) {
    const contentEditableElement = document.getElementById('your-content-editable-id');
    if (!contentEditableElement) {
      return;
    }

    const selection = window.getSelection();
    selection.removeAllRanges();

    const range = new Range();

    if (contentEditableElement.childNodes.length > 0 && contentEditableElement.firstChild.nodeType === Node.TEXT_NODE) {
      range.setStart(contentEditableElement.firstChild, position);
    } else {
      range.setStart(contentEditableElement, 0);
    }

    range.collapse(true);
    selection.addRange(range);
  }

  const getCursorPosition = () => {
    const editor = document.getElementById(`editable-div-${index}-${listIndex}`);
    const selection = window.getSelection();
    if (!selection.rangeCount) return;

    const range = selection.getRangeAt(0).cloneRange();
    range.collapse(true);
    range.setStart(editor, 0);

    const tempDiv = document.createElement("div");
    tempDiv.appendChild(range.cloneContents());

    return tempDiv.innerHTML.length - 1;
  }

  const checkSlashAndToggleVariableSelector = () => {
    const isSlash = value[cursorPositionRef.current] === '/';
    setShowVariableSelector((prev) => ({
      ...prev,
      [`${index}${listIndex}`]: isSlash
    }));
  };

  const handleCopy = (event) => {
    event.preventDefault();
    const selection = window.getSelection();
    if (!selection.rangeCount) return;

    const range = selection.getRangeAt(0);
    const div = document.createElement("div");
    div.appendChild(range.cloneContents());

    div.querySelectorAll(".inputVarSymbol, .nodeLabel, .divideSymbol, .nodeVariable").forEach(el => {
      const computedStyle = window.getComputedStyle(el);
      for (const key of computedStyle) {
        el.style[key] = computedStyle.getPropertyValue(key);
      }
    });

    event.clipboardData.setData('text/html', div.innerHTML);
  };

  const handlePaste = (event) => {
    event.preventDefault();
    const clipboardData = event.clipboardData.getData('text/html');

    const container = document.createElement("div");
    container.innerHTML = clipboardData;

    container.querySelectorAll("span, div").forEach(el => {
      el.style.color = null;
    });

    let html = container.innerHTML;

    html = html.replace(/<!--StartFragment-->/g, '');
    html = html.replace(/<!--EndFragment-->/g, '');
    html = html.substring(2, html.length - 2);

    document.execCommand("insertHTML", false, html);
  };

  return (
    <div className="inputWrapper">
      <ContentEditable
        id={`editable-div-${index}-${listIndex}`}
        name={name}
        html={value}
        onChange={handleContentChange}
        onKeyUp={handleKeyUp}
        onKeyDown={handleKeyDown}
        onClick={handleClick}
        onCopy={handleCopy}
        onPaste={handlePaste}
        placeholder="Enter text here"
        className="textareaStyle"
        tagName='article'
      />
      {showVariableSelector[`${index}${listIndex}`] && (
        <TheInputVariableDropdown
          variables={variables}
          onSelect={(selectedVariable) => handleSelectVariable(selectedVariable)}
          className="variableSelector"
        />
      )}
    </div>
  );
};

export default TextComponent;
